package com.team.panicgame.models.mauricio;

import java.util.ArrayList;
import java.util.Iterator;

import aurelienribon.tweenengine.TweenManager;

import com.badlogic.gdx.math.Vector2;
import com.team.panicgame.GameConstants;
import com.team.panicgame.Utils;
import com.team.panicgame.models.InputStatus;

public class MauricioWorld {
	private InputStatus inputStatus;
	private AssetLibrary assetLibrary;
	private TweenManager tweenManager = new TweenManager();
	
	// constants
	public static final int TOTAL_LADDERS = 5;
	public static final float ZOOM_FACTOR = GameConstants.GAME_HEIGHT * 0.25f; 
	
	// objects
	public ArrayList<Ladder> ladders;
	public Frog frog;
	public float frogVelocity = -0.1f;
	public boolean invisible = false;
	
	public MauricioWorld(InputStatus inputStatus, AssetLibrary assetLibrary){
		this.inputStatus = inputStatus;
		this.assetLibrary = assetLibrary;
		frog = new Frog(0, Frog.HEIGHT * 2f);
		ladders = new ArrayList<Ladder>();
		createLadders();
	}
	
	public void createLadders() {
		Ladder ladder = new Ladder(
			0,
			Ladder.MIN_HEIGHT * 2f,
			Ladder.MIN_WIDTH,
			Ladder.MIN_HEIGHT
		);
		ladders.add(ladder);
		for (int i = 0; i < TOTAL_LADDERS; ++i) {
			createSingleLadder();
		}
	}
	
	public void createSingleLadder() {
		Ladder lastLadder = ladders.get(ladders.size() - 1),
				newLadder;
		Vector2 p1, p2;
		while (true) {
			newLadder = new Ladder(
				(float) ((GameConstants.GAME_WIDTH - Ladder.MIN_WIDTH) * Math.random()),
				lastLadder.shape.y + GameConstants.GAME_HEIGHT / TOTAL_LADDERS,
				Ladder.MIN_WIDTH,
				Ladder.MIN_HEIGHT
			);
			p1 = new Vector2(
				lastLadder.shape.x + lastLadder.shape.width / 2f,
				lastLadder.shape.y + lastLadder.shape.height / 2f
			);
			p2 = new Vector2(
				newLadder.shape.x + lastLadder.shape.width / 2f,
				newLadder.shape.y + lastLadder.shape.height / 2f
			);
//			Gdx.app.log("createSingleLadder", p1.dst(p2) + "");
			if (Math.abs(p2.x - p1.x) <= Ladder.MAX_DISTANCE &&
					Math.abs(p2.x - p1.x) >= Ladder.MIN_DISTANCE) {
				break;
			}
		}
		ladders.add(newLadder);
	}
	
	public void detectCollision() {
		for (int i = 0; i < TOTAL_LADDERS; ++i) {
			Ladder ladder = ladders.get(i);

			if (Utils.onTop(frog.shape, ladder.shape)) {
				// the frog crashed
				frog.state = Frog.State.IDLE;
				frog.shape.y = ladder.shape.y + ladder.shape.height;
				frogVelocity = 0f;
				assetLibrary.play("land");
				break;
			}
		}
	}
	
	public void updateFrog(float delta) {
		if (frog.state == Frog.State.IDLE) {
			frog.shape.y -= delta * ZOOM_FACTOR;			
			if (inputStatus.isUp) {
				frog.state = Frog.State.JUMP;
				frogVelocity = Frog.JUMP_INITIAL_VELOCITY;
				
				// frog sound
				assetLibrary.play("frog");
			}
		}
		
		if (frogVelocity < 0) {
			frog.state = Frog.State.FALL;
		}
				
		if (frog.state != Frog.State.IDLE) {			
			
			// move left or right
			if (inputStatus.isLeft) frog.shape.x -= delta * ZOOM_FACTOR * 2f;
			if (inputStatus.isRight) frog.shape.x += delta * ZOOM_FACTOR * 2f;
			
			// move the frog
			frogVelocity = frog.move(delta, frogVelocity);
			
			// detect collision
			if (frog.state == Frog.State.FALL) {
				detectCollision();				
			}
		}
	}
	
	public void updateLadders(float delta) {
		for (Iterator<Ladder> iter = ladders.iterator(); iter.hasNext();) {
			Ladder ladder = (Ladder) iter.next();
			ladder.shape.y -= delta * ZOOM_FACTOR;
			if (ladder.shape.y + ladder.shape.height < 0f) {
				iter.remove();
			}
		}
		
		while (ladders.size() < TOTAL_LADDERS) {
			createSingleLadder();
		}
	}
	

	public void update(float delta) {
		updateFrog(delta);
		tweenManager.update(delta);
		updateLadders(delta);
	}
}